# state.rb
# Copyright (C) 2009 Akira TAGOH

# Authors:
#   Akira TAGOH  <akira@tagoh.org>

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.

require 'runit/testcase'
require 'prune/state'

class TestPRUNE__NickList < RUNIT::TestCase

  class << self
    def set_msg(msg)
      @@msg = msg
    end # def set_msg
    def get_msg
      @@msg
    end # def get_msg
  end

  def setup
    @@msg = nil
    def PRUNE._output(msg)
      TestPRUNE__NickList.set_msg(msg)
    end # def 
  end # def setup

  def teardown
    raise StandardError, sprintf("%s", @@msg) unless @@msg.nil?

    def PRUNE._output(msg)
      Kernel.printf("%s\n", msg)
    end # def 
  end # def teardown

  def test_add
    t = PRUNE::NickList.new
    assert_equal(nil, t.add(1))
    assert_match(Regexp.new("\\[BUG\\] Found an unexpected object in `PRUNE::NickList:#<PRUNE::NickList:0x[0-9a-f]+>': 1"), TestPRUNE__NickList.get_msg)
    TestPRUNE__NickList.set_msg(nil)
    assert_no_exception {t.add(PRUNE::TYPE::NickInfoStruct.new("foo"))}
    assert_equal(1, t.size)
  end # def test_add

  def test_delete
    t = PRUNE::NickList.new
    assert_equal(nil, t.add(1))
    TestPRUNE__NickList.set_msg(nil)
    assert_no_exception {t.add(PRUNE::TYPE::NickInfoStruct.new("foo"))}
    assert_equal(1, t.size)
    assert_no_exception {t.delete("bar")}
    TestPRUNE__NickList.set_msg(nil)
    assert_equal(1, t.size)
    assert_no_exception {t.delete("Foo")}
    assert_equal(0, t.size)
  end # def test_delete

  def test_include
    t = PRUNE::NickList.new
    assert_equal(nil, t.add(1))
    TestPRUNE__NickList.set_msg(nil)
    assert_no_exception {t.add(PRUNE::TYPE::NickInfoStruct.new("foo"))}
    assert_equal(true, t.include?("foo"))
    assert_equal(true, t.include?("Foo"))
    assert_equal(true, t.include?("fOo"))
    assert_equal(false, t.include?(:foo))
    assert_equal(false, t.include?("bar"))
  end # def test_include

  def test_nicks
    t = PRUNE::NickList.new
    assert_no_exception {t.add(PRUNE::TYPE::NickInfoStruct.new("fOo"))}
    assert_no_exception {t.add(PRUNE::TYPE::NickInfoStruct.new("baR"))}
    assert_equal(["fOo", "baR"], t.nicks)
  end # def test_nicks

  def test_has_oper
    t = PRUNE::NickList.new
    assert_no_exception {t.add(PRUNE::TYPE::NickInfoStruct.new("foo"))}
    assert_equal(false, t.has_oper?("foO"))
    assert_equal(false, t.has_oper?("Foo"))
    assert_equal(false, t.has_oper?("foo"))
    assert_no_exception {t.set_oper("FOO", true)}
    assert_equal(true, t.has_oper?("foO"))
    assert_equal(true, t.has_oper?("Foo"))
    assert_equal(true, t.has_oper?("foo"))
    assert_no_exception {t.set_oper("foo", false)}
    assert_equal(false, t.has_oper?("foO"))
    assert_equal(false, t.has_oper?("Foo"))
    assert_equal(false, t.has_oper?("foo"))
  end # def test_has_oper

  def test_set_oper
    # should be done in test_has_oper
  end # def test_set_oper

  def test_clear_oper
    t = PRUNE::NickList.new
    assert_no_exception {t.add(PRUNE::TYPE::NickInfoStruct.new("foo"))}
    assert_equal(false, t.has_oper?("foO"))
    assert_equal(false, t.has_oper?("Foo"))
    assert_equal(false, t.has_oper?("foo"))
    assert_no_exception {t.set_oper("FOO", true)}
    assert_equal(true, t.has_oper?("foO"))
    assert_equal(true, t.has_oper?("Foo"))
    assert_equal(true, t.has_oper?("foo"))
    assert_no_exception {t.clear_oper}
    assert_equal(false, t.has_oper?("foO"))
    assert_equal(false, t.has_oper?("Foo"))
    assert_equal(false, t.has_oper?("foo"))
  end # def test_clear_oper

  def test_opers
    t = PRUNE::NickList.new
    assert_no_exception {t.add(PRUNE::TYPE::NickInfoStruct.new("foo"))}
    assert_no_exception {t.add(PRUNE::TYPE::NickInfoStruct.new("bAr"))}
    assert_no_exception {t.add(PRUNE::TYPE::NickInfoStruct.new("baZ"))}
    assert_equal(true, t.set_oper("baR", true))
    assert_equal(true, t.set_oper("bAz", true))
    assert_equal(["bAr", "baZ"], t.opers.sort)
  end # def test_opers

  def test_has_voice
    t = PRUNE::NickList.new
    assert_no_exception {t.add(PRUNE::TYPE::NickInfoStruct.new("foo"))}
    assert_equal(false, t.has_voice?("foO"))
    assert_equal(false, t.has_voice?("Foo"))
    assert_equal(false, t.has_voice?("foo"))
    assert_no_exception {t.set_voice("FOO", true)}
    assert_equal(true, t.has_voice?("foO"))
    assert_equal(true, t.has_voice?("Foo"))
    assert_equal(true, t.has_voice?("foo"))
    assert_no_exception {t.set_voice("foo", false)}
    assert_equal(false, t.has_voice?("foO"))
    assert_equal(false, t.has_voice?("Foo"))
    assert_equal(false, t.has_voice?("foo"))
  end # def test_has_voice

  def test_set_voice
    # should be done in test_has_voice
  end # def test_set_voice

  def test_clear_voice
    t = PRUNE::NickList.new
    assert_no_exception {t.add(PRUNE::TYPE::NickInfoStruct.new("foo"))}
    assert_equal(false, t.has_voice?("foO"))
    assert_equal(false, t.has_voice?("Foo"))
    assert_equal(false, t.has_voice?("foo"))
    assert_no_exception {t.set_voice("FOO", true)}
    assert_equal(true, t.has_voice?("foO"))
    assert_equal(true, t.has_voice?("Foo"))
    assert_equal(true, t.has_voice?("foo"))
    assert_no_exception {t.clear_voice}
    assert_equal(false, t.has_voice?("foO"))
    assert_equal(false, t.has_voice?("Foo"))
    assert_equal(false, t.has_voice?("foo"))
  end # def test_clear_voice

  def test_voices
    t = PRUNE::NickList.new
    assert_no_exception {t.add(PRUNE::TYPE::NickInfoStruct.new("foo"))}
    assert_no_exception {t.add(PRUNE::TYPE::NickInfoStruct.new("bAr"))}
    assert_no_exception {t.add(PRUNE::TYPE::NickInfoStruct.new("baZ"))}
    assert_equal(true, t.set_voice("foo", true))
    assert_equal(true, t.set_voice("bAz", true))
    assert_equal(["baZ", "foo"], t.voices.sort)
  end # def test_voices

  def test_change_nick
    t = PRUNE::NickList.new
    assert_no_exception {t.add(PRUNE::TYPE::NickInfoStruct.new("foo"))}
    assert_no_exception {t.add(PRUNE::TYPE::NickInfoStruct.new("baR"))}
    assert_equal(nil, t.change_nick("baz", "foo"))
    assert_equal(true, t.include?("fOo"))
    assert_equal(true, t.include?("foo"))
    assert_no_exception {t.change_nick("Foo", "fOo2")}
    assert_equal(false, t.include?("fOo"))
    assert_equal(false, t.include?("foo"))
    assert_equal(nil, t.change_nick("bar", "foo2"))
    TestPRUNE__NickList.set_msg(nil)
  end # def test_change_nick

end # class TestPRUNE__NickList

class TestPRUNE__ModeList < RUNIT::TestCase

  class << self
    def set_msg(msg)
      @@msg = msg
    end # def set_msg
    def get_msg
      @@msg
    end # def get_msg
  end

  def setup
    @@msg = nil
    def PRUNE._output(msg)
      TestPRUNE__ModeList.set_msg(msg)
    end # def 
  end # def setup

  def teardown
    raise StandardError, sprintf("%s", @@msg) unless @@msg.nil?

    def PRUNE._output(msg)
      Kernel.printf("%s\n", msg)
    end # def 
  end # def teardown

  def test_base__modename
    t = PRUNE::ModeList.new
    assert_equal([], t.modename(0))
    assert_equal([nil], t.modename(PRUNE::ModeList::MODE_UNINITIALIZED))
    assert_equal(["AWAY"], t.modename(PRUNE::ModeList::MODE_AWAY))
    assert_equal(["INVISIBLE"], t.modename(PRUNE::ModeList::MODE_INVISIBLE))
    assert_equal(["WALLOPS"], t.modename(PRUNE::ModeList::MODE_WALLOPS))
    assert_equal(["RESTRICTED"], t.modename(PRUNE::ModeList::MODE_RESTRICTED))
    assert_equal(["OPER"], t.modename(PRUNE::ModeList::MODE_OPER))
    assert_equal(["LOCAL_OPER"], t.modename(PRUNE::ModeList::MODE_LOCAL_OPER))
    assert_equal(["SERVER_NOTICE"], t.modename(PRUNE::ModeList::MODE_SERVER_NOTICE))
    assert_equal(["AWAY", "OPER"], t.modename(PRUNE::ModeList::MODE_AWAY|PRUNE::ModeList::MODE_OPER))
  end # def test_base__modename

  def test_base__to_s
    # basically should be done in test_set_mode
  end # def test_base__to_s

  def test_base__clear
    # basically should be done in test_set_mode
  end # def test_base__clear

  def test_base__modeinfo
    t = PRUNE::ModeList.new
    assert_equal(nil, t.modeinfo(0))
    assert_equal(PRUNE::ModeList::MODE_AWAY, t.modeinfo('a'))
    assert_equal(PRUNE::ModeList::MODE_INVISIBLE, t.modeinfo('i'))
    assert_equal(PRUNE::ModeList::MODE_WALLOPS, t.modeinfo('w'))
    assert_equal(PRUNE::ModeList::MODE_RESTRICTED, t.modeinfo('r'))
    assert_equal(PRUNE::ModeList::MODE_OPER, t.modeinfo('o'))
    assert_equal(PRUNE::ModeList::MODE_LOCAL_OPER, t.modeinfo('O'))
    assert_equal(PRUNE::ModeList::MODE_SERVER_NOTICE, t.modeinfo('s'))
  end # def test_base__modeinfo

  def test_availmode
    assert_equal("Oaiorsw", PRUNE::ModeList.availmode.split(//).sort.join)
  end # def test_availmode

  def test_set_mode
    t = PRUNE::ModeList.new
    assert_equal(nil, t.set_mode(0, true))
    assert_equal(nil, t.mode[0])
    assert_equal(nil, t.set_mode(0, false))
    assert_equal(nil, t.mode[0])
    assert_equal(nil, t.set_mode(PRUNE::ModeList::MODE_UNINITIALIZED, true))
    assert_equal(nil, t.mode[PRUNE::ModeList::MODE_UNINITIALIZED])
    assert_equal("+", t.to_s)
    assert_equal(nil, t.set_mode(PRUNE::ModeList::MODE_UNINITIALIZED, false))
    assert_equal(nil, t.mode[PRUNE::ModeList::MODE_UNINITIALIZED])
    assert_equal("+", t.to_s)
    assert_equal(true, t.set_mode(PRUNE::ModeList::MODE_AWAY, true))
    assert_equal(true, t.mode[PRUNE::ModeList::MODE_AWAY])
    assert_equal("+a", t.to_s)
    assert_equal(false, t.set_mode(PRUNE::ModeList::MODE_OPER, false))
    assert_equal(false, t.mode[PRUNE::ModeList::MODE_OPER])
    assert_equal("+a", t.to_s)
    assert_equal(true, t.set_mode(PRUNE::ModeList::MODE_LOCAL_OPER, true))
    assert_equal(true, t.mode[PRUNE::ModeList::MODE_LOCAL_OPER])
    assert_equal("+aO", t.to_s)
    assert_equal(nil, t.set_mode(0xffff, true))
    assert_equal("[BUG] unknown mode: 65281", TestPRUNE__ModeList.get_msg)
    TestPRUNE__ModeList.set_msg(nil)
    assert_equal(true, t.mode[PRUNE::ModeList::MODE_AWAY])
    assert_equal(true, t.mode[PRUNE::ModeList::MODE_INVISIBLE])
    assert_equal(true, t.mode[PRUNE::ModeList::MODE_WALLOPS])
    assert_equal(true, t.mode[PRUNE::ModeList::MODE_RESTRICTED])
    assert_equal(true, t.mode[PRUNE::ModeList::MODE_OPER])
    assert_equal(true, t.mode[PRUNE::ModeList::MODE_LOCAL_OPER])
    assert_equal(true, t.mode[PRUNE::ModeList::MODE_SERVER_NOTICE])
    assert_equal(["+" << PRUNE::ModeList.availmode.split(//).sort.join].join(' '), t.to_s.split(/ /)[0].split(//).delete_if{|x|x=='+'}.sort.unshift('+').join)
    assert_equal(nil, t.mode[65281])
    assert_equal(nil, t.set_mode(PRUNE::ModeList::MODE_UNINITIALIZED|PRUNE::ModeList::MODE_WALLOPS, false))
    assert_equal(true, t.mode[PRUNE::ModeList::MODE_AWAY])
    assert_equal(true, t.mode[PRUNE::ModeList::MODE_INVISIBLE])
    assert_equal(false, t.mode[PRUNE::ModeList::MODE_WALLOPS])
    assert_equal(true, t.mode[PRUNE::ModeList::MODE_RESTRICTED])
    assert_equal(true, t.mode[PRUNE::ModeList::MODE_OPER])
    assert_equal(true, t.mode[PRUNE::ModeList::MODE_LOCAL_OPER])
    assert_equal(true, t.mode[PRUNE::ModeList::MODE_SERVER_NOTICE])
    assert_equal(nil, t.mode[1])
    assert_equal("[BUG] unknown mode: 1", TestPRUNE__ModeList.get_msg)
    TestPRUNE__ModeList.set_msg(nil)

    assert_equal(false, t.set_mode(PRUNE::ModeList::MODE_AWAY, 0))
    assert_equal(false, t.mode[PRUNE::ModeList::MODE_AWAY])
    assert_no_exception {t.clear}
    assert_equal("+", t.to_s)
  end # def test_set_mode

  def test_base__mode
    # basically should be done in test_set_mode
    t = PRUNE::ModeList.new
    assert_exception(NoMethodError) {t.mode = 0}
  end # def test_base__mode

end # class TestPRUNE__ModeList

class TestPRUNE__ChannelModeList < RUNIT::TestCase

  class << self
    def set_msg(msg)
      @@msg = msg
    end # def set_msg
    def get_msg
      @@msg
    end # def get_msg
  end

  def setup
    @@msg = nil
    def PRUNE._output(msg)
      TestPRUNE__ChannelModeList.set_msg(msg)
    end # def 
  end # def setup

  def teardown
    raise StandardError, sprintf("%s", @@msg) unless @@msg.nil?

    def PRUNE._output(msg)
      Kernel.printf("%s\n", msg)
    end # def 
  end # def teardown

  def test_functional
    assert_exception(ArgumentError) {t = PRUNE::ChannelModeList.new(0)}
  end # def test_functional

  def test_base__modename
    t = PRUNE::ChannelModeList.new(PRUNE::ChannelState.new("#foo"))
    assert_equal([], t.modename(0))
    assert_equal([nil], t.modename(PRUNE::ChannelModeList::MODE_UNINITIALIZED))
    assert_equal(["INVITE"], t.modename(PRUNE::ChannelModeList::MODE_INVITE))
    assert_equal(["MODERATED"], t.modename(PRUNE::ChannelModeList::MODE_MODERATED))
    assert_equal(["AUTO_INVITE"], t.modename(PRUNE::ChannelModeList::MODE_AUTO_INVITE))
    assert_equal(["OPER"], t.modename(PRUNE::ChannelModeList::MODE_OPER))
    assert_equal(["VOICE"], t.modename(PRUNE::ChannelModeList::MODE_VOICE))
    assert_equal(["SECRET"], t.modename(PRUNE::ChannelModeList::MODE_SECRET))
    assert_equal(["KEY"], t.modename(PRUNE::ChannelModeList::MODE_KEY))
    assert_equal(["LIMIT"], t.modename(PRUNE::ChannelModeList::MODE_LIMIT))
    assert_equal(["BAN"], t.modename(PRUNE::ChannelModeList::MODE_BAN))
    assert_equal(["EXCEPT"], t.modename(PRUNE::ChannelModeList::MODE_EXCEPT))
    assert_equal(["TOPIC"], t.modename(PRUNE::ChannelModeList::MODE_TOPIC))
    assert_equal(["PRIVATE"], t.modename(PRUNE::ChannelModeList::MODE_PRIVATE))
    assert_equal(["ANONYMOUS"], t.modename(PRUNE::ChannelModeList::MODE_ANONYMOUS))
    assert_equal(["NO_EXTERNAL_MSGS"], t.modename(PRUNE::ChannelModeList::MODE_NO_EXTERNAL_MSGS))
    assert_equal(["TOPIC", "NO_EXTERNAL_MSGS"], t.modename(PRUNE::ChannelModeList::MODE_TOPIC|PRUNE::ChannelModeList::MODE_NO_EXTERNAL_MSGS))
  end # def test_base__modename

  def test_base__to_s
    # basically should be done in test_set_mode
  end # def test_base__to_s

  def test_base__clear
    # basically should be done in test_set_mode
  end # def test_base__clear

  def test_availmode
    assert_equal("Iabeiklmnopstv", PRUNE::ChannelModeList.availmode.split(//).sort.join)
  end # def test_availmode

  def test_modeinfo
    t = PRUNE::ChannelModeList.new(PRUNE::ChannelState.new("#foo"))
    assert_equal(nil, t.modeinfo(0))
    assert_equal([PRUNE::ChannelModeList::MODE_INVITE, false], t.modeinfo('i'))
    assert_equal([PRUNE::ChannelModeList::MODE_MODERATED, false], t.modeinfo('m'))
    assert_equal([PRUNE::ChannelModeList::MODE_AUTO_INVITE, true], t.modeinfo('I'))
    assert_equal([PRUNE::ChannelModeList::MODE_OPER, true], t.modeinfo('o'))
    assert_equal([PRUNE::ChannelModeList::MODE_VOICE, true], t.modeinfo('v'))
    assert_equal([PRUNE::ChannelModeList::MODE_SECRET, false], t.modeinfo('s'))
    assert_equal([PRUNE::ChannelModeList::MODE_KEY, true], t.modeinfo('k'))
    assert_equal([PRUNE::ChannelModeList::MODE_LIMIT, true], t.modeinfo('l'))
    assert_equal([PRUNE::ChannelModeList::MODE_BAN, true], t.modeinfo('b'))
    assert_equal([PRUNE::ChannelModeList::MODE_EXCEPT, true], t.modeinfo('e'))
    assert_equal([PRUNE::ChannelModeList::MODE_TOPIC, false], t.modeinfo('t'))
    assert_equal([PRUNE::ChannelModeList::MODE_PRIVATE, false], t.modeinfo('p'))
    assert_equal([PRUNE::ChannelModeList::MODE_ANONYMOUS, false], t.modeinfo('a'))
    assert_equal([PRUNE::ChannelModeList::MODE_NO_EXTERNAL_MSGS, false], t.modeinfo('n'))
  end # def test_modeinfo

  def test_set_mode
    t = PRUNE::ChannelModeList.new(x = PRUNE::ChannelState.new("#foo"))
    assert_equal(nil, t.set_mode(0, true))
    assert_equal(nil, t.mode[0])
    assert_equal(nil, t.set_mode(0, false))
    assert_equal(nil, t.mode[0])
    assert_equal(nil, t.set_mode(PRUNE::ChannelModeList::MODE_UNINITIALIZED, true))
    assert_equal(nil, t.mode[PRUNE::ChannelModeList::MODE_UNINITIALIZED])
    assert_equal("+", t.to_s)
    assert_equal(nil, t.set_mode(PRUNE::ChannelModeList::MODE_UNINITIALIZED, false))
    assert_equal(nil, t.mode[PRUNE::ChannelModeList::MODE_UNINITIALIZED])
    assert_equal("+", t.to_s)
    assert_equal(true, t.set_mode(PRUNE::ChannelModeList::MODE_INVITE, true))
    assert_equal(true, t.mode[PRUNE::ChannelModeList::MODE_INVITE])
    assert_equal("+i", t.to_s)
    assert_equal(true, t.set_mode(PRUNE::ChannelModeList::MODE_MODERATED, true))
    assert_equal(true, t.mode[PRUNE::ChannelModeList::MODE_MODERATED])
    assert_equal("+im", t.to_s)
    assert_equal(false, t.set_mode(PRUNE::ChannelModeList::MODE_MODERATED, false))
    assert_equal(false, t.mode[PRUNE::ChannelModeList::MODE_MODERATED])
    assert_equal("+i", t.to_s)
    assert_exception(ArgumentError) {t.set_mode(PRUNE::ChannelModeList::MODE_AUTO_INVITE, true, 0)}
    assert_exception(ArgumentError) {t.set_mode(PRUNE::ChannelModeList::MODE_AUTO_INVITE, true, :foo)}
    assert_equal(true, t.set_mode(PRUNE::ChannelModeList::MODE_AUTO_INVITE, true, "foo"))
    assert_equal(["foo!*@*"], t.mode[PRUNE::ChannelModeList::MODE_AUTO_INVITE])
    assert_equal("+iI foo!*@*", t.to_s)
    assert_no_exception {x.join("bar")}
    assert_equal(true, t.set_mode(PRUNE::ChannelModeList::MODE_OPER, true, "bar"))
    assert_equal(["bar"], x.opers)
    assert_equal(["bar"], t.mode[PRUNE::ChannelModeList::MODE_OPER])
    assert_equal("+iIo foo!*@* bar", t.to_s)
    assert_no_exception {x.join("foo")}
    assert_equal(true, t.set_mode(PRUNE::ChannelModeList::MODE_VOICE, true, "foo"))
    assert_equal(["foo"], t.mode[PRUNE::ChannelModeList::MODE_VOICE])
    assert_equal("+iIov foo!*@* bar foo", t.to_s)
    assert_equal(false, t.set_mode(PRUNE::ChannelModeList::MODE_SECRET, false))
    assert_equal(false, t.mode[PRUNE::ChannelModeList::MODE_SECRET])
    assert_equal("+iIov foo!*@* bar foo", t.to_s)
    assert_equal(true, t.set_mode(PRUNE::ChannelModeList::MODE_KEY, true, "blahblahblah"))
    assert_exception(ArgumentError) {t.set_mode(PRUNE::ChannelModeList::MODE_KEY, true, 0)}
    assert_exception(ArgumentError) {t.set_mode(PRUNE::ChannelModeList::MODE_KEY, true, :foo)}
    assert_equal("blahblahblah", t.mode[PRUNE::ChannelModeList::MODE_KEY])
    assert_equal("+iIovk foo!*@* bar foo blahblahblah", t.to_s)
    assert_equal(true, t.set_mode(PRUNE::ChannelModeList::MODE_LIMIT, true, 10))
    assert_equal(10, t.mode[PRUNE::ChannelModeList::MODE_LIMIT])
    assert_equal("+iIovkl foo!*@* bar foo blahblahblah 10", t.to_s)
    assert_equal(true, t.set_mode(PRUNE::ChannelModeList::MODE_BAN, true, "*!foo@*.com"))
    assert_equal(["*!foo@*.com"], t.mode[PRUNE::ChannelModeList::MODE_BAN])
    assert_equal("+iIovklb foo!*@* bar foo blahblahblah 10 *!foo@*.com", t.to_s)
    assert_equal(true, t.set_mode(PRUNE::ChannelModeList::MODE_BAN, true, "spam*@*.com"))
    assert_equal(["*!foo@*.com", "spam*!*@*.com"], t.mode[PRUNE::ChannelModeList::MODE_BAN])
    assert_equal("+iIovklbb foo!*@* bar foo blahblahblah 10 *!foo@*.com spam*!*@*.com", t.to_s)
    assert_equal(true, t.set_mode(PRUNE::ChannelModeList::MODE_BAN, true, "*spam"))
    assert_equal(["*!foo@*.com", "spam*!*@*.com", "*spam!*@*"], t.mode[PRUNE::ChannelModeList::MODE_BAN])
    assert_equal("+iIovklbbb foo!*@* bar foo blahblahblah 10 *!foo@*.com spam*!*@*.com *spam!*@*", t.to_s)
    assert_equal(false, t.set_mode(PRUNE::ChannelModeList::MODE_TOPIC, false))
    assert_equal(false, t.mode[PRUNE::ChannelModeList::MODE_TOPIC])
    assert_equal("+iIovklbbb foo!*@* bar foo blahblahblah 10 *!foo@*.com spam*!*@*.com *spam!*@*", t.to_s)
    assert_equal(true, t.set_mode(PRUNE::ChannelModeList::MODE_PRIVATE, true))
    assert_equal(true, t.mode[PRUNE::ChannelModeList::MODE_PRIVATE])
    assert_equal("+iIovklbbbp foo!*@* bar foo blahblahblah 10 *!foo@*.com spam*!*@*.com *spam!*@*", t.to_s)
    assert_equal(false, t.set_mode(PRUNE::ChannelModeList::MODE_ANONYMOUS, false))
    assert_equal(false, t.mode[PRUNE::ChannelModeList::MODE_ANONYMOUS])
    assert_equal("+iIovklbbbp foo!*@* bar foo blahblahblah 10 *!foo@*.com spam*!*@*.com *spam!*@*", t.to_s)
    assert_equal(true, t.set_mode(PRUNE::ChannelModeList::MODE_NO_EXTERNAL_MSGS, true))
    assert_equal(true, t.mode[PRUNE::ChannelModeList::MODE_NO_EXTERNAL_MSGS])
    assert_equal("+iIovklbbbpn foo!*@* bar foo blahblahblah 10 *!foo@*.com spam*!*@*.com *spam!*@*", t.to_s)
    TestPRUNE__ChannelModeList.set_msg(nil)
    assert_equal(nil, t.set_mode(0xffff, true))
    # we don't support the multiple mode set
    assert_equal("[BUG] unknown mode: 65535", TestPRUNE__ChannelModeList.get_msg)
    TestPRUNE__ChannelModeList.set_msg(nil)

    assert_no_exception {t.clear}
    assert_equal("+ov bar foo", t.to_s)
    assert_equal(nil, t.mode[PRUNE::ChannelModeList::MODE_AUTO_INVITE])
    assert_equal(["bar"], t.mode[PRUNE::ChannelModeList::MODE_OPER])
    assert_equal(["foo"], t.mode[PRUNE::ChannelModeList::MODE_VOICE])
    assert_equal(nil, t.mode[PRUNE::ChannelModeList::MODE_KEY])
    assert_equal(nil, t.mode[PRUNE::ChannelModeList::MODE_BAN])
    assert_equal(nil, t.mode[PRUNE::ChannelModeList::MODE_EXCEPT])
  end # def test_set_mode

  def test_base__mode
    # basically should be done in test_set_mode
    t = PRUNE::ChannelModeList.new(PRUNE::ChannelState.new("#foo"))
    assert_exception(NoMethodError) {t.mode = 0}
  end # def test_base__mode

end # class TestPRUNE__ChannelModeList

class TestPRUNE__ChannelState < RUNIT::TestCase

  class << self
    def set_msg(msg)
      @@msg = msg
    end # def set_msg
    def get_msg
      @@msg
    end # def get_msg
  end

  def setup
    @@msg = nil
    def PRUNE._output(msg)
      TestPRUNE__ChannelState.set_msg(msg)
    end # def 
  end # def setup

  def teardown
    raise StandardError, sprintf("%s", @@msg) unless @@msg.nil?

    def PRUNE._output(msg)
      Kernel.printf("%s\n", msg)
    end # def 
  end # def teardown

  def test_functional
    assert_exception(ArgumentError) {t = PRUNE::ChannelState.new(:foo)}
    assert_exception(ArgumentError) {t = PRUNE::ChannelState.new(0)}
    assert_exception(ArgumentError) {t = PRUNE::ChannelState.new("foo")}
    assert_no_exception {t = PRUNE::ChannelState.new("#foo")}
    assert_no_exception {t = PRUNE::ChannelState.new("%foo")}
    assert_no_exception {t = PRUNE::ChannelState.new("&foo")}
    assert_no_exception {t = PRUNE::ChannelState.new("!foo")}
  end # def test_functional

  def test_topic
    # should be done in test_set_topic
  end # def test_topic

  def test_set_topic
    t = PRUNE::ChannelState.new("#foo")
    assert_no_exception {t.topic = "foo"}
    assert_equal("foo", t.topic)
  end # def test_set_topic

  def test_joined_
    # should be done in test_join
  end # def test_joined_

  def test_join
    t = PRUNE::ChannelState.new("#foo")
    assert_equal(false, t.joined?("foo"))
    assert_no_exception {t.join("Foo")}
    assert_equal(true, t.joined?("foo"))
    assert_no_exception {t.leave("fOO")}
    assert_equal(false, t.joined?("foO"))
  end # def test_join

  def test_leave
    # should be done in test_join
  end # def test_leave

  def test_has_oper_
    # should be done in test_set_oper
  end # def test_has_oper_

  def test_set_oper
    t = PRUNE::ChannelState.new("#foo")
    assert_no_exception {t.join("Foo")}
    assert_no_exception {t.join("bAr")}
    assert_no_exception {t.set_oper("foo", true)}
    assert_equal(["Foo"], t.opers)
    assert_equal(true, t.has_oper?("fOo"))
    assert_equal(true, t.has_oper?("foo"))
    assert_equal(true, t.has_oper?("Foo"))
    assert_no_exception {t.set_oper("bar", false)}
    assert_equal(["Foo"], t.opers)
    assert_no_exception {t.set_oper("bar", 0)}
    assert_equal(["Foo"], t.opers)
    assert_no_exception {t.set_oper("bar", 1)}
    assert_equal(["Foo"], t.opers)
    assert_equal(false, t.has_oper?("BAR"))
    assert_equal(false, t.has_oper?("bar"))
    assert_no_exception {t.clear_oper}
    assert_equal([], t.opers)
  end # def test_set_oper

  def test_clear_oper
    # should be done in test_set_oper
  end # def test_clear_oper

  def test_opers
    # should be done in test_set_oper
  end # def test_opers

  def test_has_voice_
    # should be done in test_set_voice
  end # def test_has_voice_

  def test_set_voice
    t = PRUNE::ChannelState.new("#foo")
    assert_no_exception {t.join("Foo")}
    assert_no_exception {t.join("bAr")}
    assert_no_exception {t.set_voice("foo", true)}
    assert_equal(["Foo"], t.voices)
    assert_equal(true, t.has_voice?("foo"))
    assert_equal(true, t.has_voice?("fOo"))
    assert_equal(true, t.has_voice?("Foo"))
    assert_no_exception {t.set_voice("bar", false)}
    assert_equal(["Foo"], t.voices)
    assert_no_exception {t.set_voice("bar", 0)}
    assert_equal(["Foo"], t.voices)
    assert_no_exception {t.set_voice("bar", 1)}
    assert_equal(["Foo"], t.voices)
    assert_equal(false, t.has_voice?("BAR"))
    assert_equal(false, t.has_voice?("bar"))
    assert_no_exception {t.clear_voice}
    assert_equal([], t.voices)
  end # def test_set_voice

  def test_clear_voice
    # should be done in test_set_voice
  end # def test_clear_voice

  def test_voices
    # should be done in test_set_voice
  end # def test_voices

  def test_change_nick
    t = PRUNE::ChannelState.new("#foo")
    assert_no_exception {t.join("Foo")}
    assert_no_exception {t.join("bAr")}
    assert_no_exception {t.change_nick("foo", "bar")}
    assert_equal("WARNING ***: The nick name `\"bar\"' has already been in use.", TestPRUNE__ChannelState.get_msg)
    TestPRUNE__ChannelState.set_msg(nil)
    assert_equal(["Foo", "bAr"], t.nicks.sort)
    assert_no_exception {t.change_nick("baz", "foo")}
    assert_match(Regexp.new("\\[BUG\\] No such nick name in PRUNE::NickList:#<PRUNE::NickList:0x[0-9a-f]+>: \"baz\""), TestPRUNE__ChannelState.get_msg)
    TestPRUNE__ChannelState.set_msg(nil)
    assert_no_exception {t.change_nick("fOo", "baZ")}
    assert_equal(["bAr", "baZ"], t.nicks.sort)
  end # def test_change_nick

  def test_has_mode_
    t = PRUNE::ChannelState.new("#foo")
    assert_no_exception {t.join("Foo")}
    assert_no_exception {t.join("baR")}
    assert_equal(false, t.has_mode?(PRUNE::ChannelModeList::MODE_INVITE))
    assert_no_exception {t.set_mode("+i")}
    assert_equal(true, t.has_mode?(PRUNE::ChannelModeList::MODE_INVITE))
    assert_equal("+i", t.mode_string)
    assert_no_exception {t.set_mode("-i")}
    assert_equal(false, t.has_mode?(PRUNE::ChannelModeList::MODE_INVITE))
    assert_equal("+", t.mode_string)
    assert_no_exception {t.set_mode("+o", "foo")}
    assert_equal(true, t.has_mode?(PRUNE::ChannelModeList::MODE_OPER))
    assert_equal(true, t.has_oper?("Foo"))
    assert_equal("+o Foo", t.mode_string)
    assert_no_exception {t.set_mode("+be", "bar", "foo")}
    assert_equal(true, t.has_mode?(PRUNE::ChannelModeList::MODE_BAN))
    assert_equal(true, t.has_mode?(PRUNE::ChannelModeList::MODE_EXCEPT))
    assert_equal("+obe Foo bar!*@* foo!*@*", t.mode_string)
    assert_equal(["OPER:Foo", "BAN:bar!*@*", "EXCEPT:foo!*@*"], t.mode)
    assert_equal(["Foo"], t.mode(PRUNE::ChannelModeList::MODE_OPER))
    assert_no_exception {t.set_mode("+o", "bar")}
    assert_equal(["Foo", "baR"], t.mode(PRUNE::ChannelModeList::MODE_OPER))
    assert_no_exception {t.clear_mode}
    assert_equal("+oo Foo baR", t.mode_string)
  end # def test_has_mode_

  def test_mode
    # should be done in test_has_mode_
  end # def test_mode

  def test_mode_string
    # should be done in test_has_mode_
    t = PRUNE::ChannelState.new("#foo")
    assert_no_exception {t.join("foo")}
    assert_no_exception {t.set_oper("foo", true)}
    assert_equal(["foo"], t.opers)
    assert_equal("+o foo", t.mode_string)
  end # def test_mode_string

  def test_set_mode
    # should be done in test_has_mode_
  end # def test_set_mode

  def test_clear_mode
    # should be done in test_has_mode_
  end # def test_clear_mode

end # class TestPRUNE__ChannelState

class TestPRUNE__IRCState < RUNIT::TestCase

  class << self
    def set_msg(msg)
      @@msg = msg
    end # def set_msg
    def get_msg
      @@msg
    end # def get_msg
  end

  def setup
    @@msg = nil
    def PRUNE._output(msg)
      TestPRUNE__IRCState.set_msg(msg)
    end # def 
  end # def setup

  def teardown
    def PRUNE._output(msg)
      Kernel.printf("%s\n", msg)
    end # def 
  end # def teardown

  def test_functional
    assert_no_exception {t = PRUNE::IRCState.new("nick", "user", "name", "host")}
    assert_exception(ArgumentError, "Invalid nick name: nick") {t = PRUNE::IRCState.new(:nick, "user", "name", "host")}
    assert_exception(ArgumentError, "Invalid user name: user") {t = PRUNE::IRCState.new("nick", :user, "name", "host")}
    assert_exception(TypeError, "Can't convert Fixnum into String") {t = PRUNE::IRCState.new("nick", "user", 0, "host")}
    assert_exception(TypeError, "Can't convert Symbol into String") {t = PRUNE::IRCState.new("nick", "user", :name, "host")}
    assert_exception(TypeError, "Can't convert Fixnum into String") {t = PRUNE::IRCState.new("nick", "user", "name", 0)}
    assert_exception(TypeError, "Can't convert Symbol into String") {t = PRUNE::IRCState.new("nick", "user", "name", :host)}
  end # def test_functional

  def test_nick
    t = PRUNE::IRCState.new("foo", "bar", "blahblahblah", "example.com")
    assert_equal("foo", t.nick)
    assert_equal("bar", t.user)
    assert_equal("blahblahblah", t.name)
    assert_equal("example.com", t.host)
  end # def test_nick

  def test_nick_
    # should be done in test_nick
  end # def test_nick_

  def test_user
    # should be done in test_nick
  end # def test_user

  def test_name
    # should be done in test_nick
  end # def test_name

  def test_host
    # should be done in test_nick
  end # def test_host

  def test_connected
    t = PRUNE::IRCState.new("nick", "user", "name", "host")
    assert_equal(false, t.connected?)
    assert_no_exception {t.connected = true}
    assert_equal(true, t.connected?)
    assert_no_exception {t.connected = false}
    assert_equal(false, t.connected?)
  end # def test_connected

  def test_connected_
    # should be done in test_connected
  end # def test_connected_

  def test_listen
    t = PRUNE::IRCState.new("nick", "user", "name", "host")
    assert_equal(false, t.listen?)
    assert_no_exception {t.listened = true}
    assert_equal(true, t.listen?)
    assert_no_exception {t.listened = false}
    assert_equal(false, t.listen?)
  end # def test_listen

  def test_listened_
    # should be done in test_listen
  end # def test_listened_

  def test_authenticated
    t = PRUNE::IRCState.new("nick", "user", "name", "host")
    assert_equal(false, t.authenticated?)
    assert_exception(PRUNE::Error::NotYetConnected) {t.authenticated = true}
    assert_equal(false, t.authenticated?)
    assert_no_exception {t.connected = true}
    assert_no_exception {t.authenticated = true}
    assert_equal(true, t.authenticated?)
    assert_no_exception {t.authenticated = false}
    assert_no_exception {t.loggedin = true}
    assert_exception(PRUNE::Error::AlreadyLoggedIn) {t.authenticated = true}
    assert_no_exception {t.connected = false}
    assert_equal(false, t.loggedin?)
    assert_equal(false, t.authenticated?)

    assert_no_exception {t.listened = true}
    assert_no_exception {t.authenticated = true}
    assert_equal(true, t.authenticated?)
    assert_no_exception {t.authenticated = false}
    assert_no_exception {t.loggedin = true}
    assert_exception(PRUNE::Error::AlreadyLoggedIn) {t.authenticated = true}
    assert_no_exception {t.listened = false}
    assert_equal(false, t.loggedin?)
    assert_equal(false, t.authenticated?)
  end # def test_authenticated

  def test_authenticated_
    # should be done in test_authenticated
  end # def test_authenticated_

  def test_loggedin
    t = PRUNE::IRCState.new("nick", "user", "name", "host")
    assert_equal(false, t.loggedin?)
    assert_exception(PRUNE::Error::NotYetConnected) {t.loggedin = true}
    assert_equal(false, t.loggedin?)
    assert_no_exception {t.connected = true}
    assert_no_exception {t.loggedin = true}
    assert_equal(true, t.loggedin?)
    assert_exception(PRUNE::Error::UnableToLogOut) {t.loggedin = false}
    assert_no_exception {t.connected = false}
    assert_equal(false, t.connected?)
    assert_equal(false, t.loggedin?)
  end # def test_loggedin

  def test_loggedin_
    # should be done in test_loggedin
  end # def test_loggedin_

  def test_channel
    t = PRUNE::IRCState.new("foo", "bar", "blahblahblah", "example.com")
    assert_exception(NoMethodError) {t.channel = 0}
    assert_no_exception {t.channel(0)}
    assert_match(Regexp.new("\\[BUG\\] No such channel `0' available in PRUNE::IRCState:#<PRUNE::IRCState:0x[0-9a-f]+>"), TestPRUNE__IRCState.get_msg)
    TestPRUNE__IRCState.set_msg(nil)
  end # def test_channel

  def test_channels
    # should be done in test_join
  end # def test_channels

  def test_join
    t = PRUNE::IRCState.new("nick", "user", "name", "host")
    assert_no_exception {t.join("#foo", "nick")}
    assert_no_exception {t.join("#foo", "nick")}
    assert_match(Regexp.new("\\[BUG\\] `\"nick\"' has already joined a channel `\"#foo\"'"), TestPRUNE__IRCState.get_msg)
    TestPRUNE__IRCState.set_msg(nil)
    assert_no_exception {t.join("#bar", "nick")}
    assert_equal(["#bar", "#foo"], t.channels.sort)
    assert_no_exception {t.join("#foo", "bar")}
    assert_equal(["bar", "nick"], t.channel("#foo").nicks.sort)
    assert_no_exception {t.leave("#foo", "nick")}
    assert_equal(false, t.joined?("#foo", "nick"))
  end # def test_join

  def test_leave
    # should be done in test_join
  end # def test_leave

  def test_quit
    t = PRUNE::IRCState.new("nick", "user", "name", "host")
    assert_no_exception {t.join("#foo", "nick")}
    assert_no_exception {t.join("#bar", "nick")}
    assert_no_exception {t.join("#foo", "bar")}
    assert_no_exception {t.join("#bar", "baz")}
    assert_equal(["bar", "nick"], t.channel("#foo").nicks.sort)
    assert_equal(["baz", "nick"], t.channel("#bar").nicks.sort)
    assert_no_exception {t.quit("bar")}
    assert_equal(["nick"], t.channel("#foo").nicks.sort)
    assert_equal(["baz", "nick"], t.channel("#bar").nicks.sort)
    assert_no_exception {t.quit("nick")}
  end # def test_quit

  def test_has_mode
    # should be done in test_set_mode
  end # def test_has_mode

  def test_mode
    # should be done in test_set_mode
  end # def test_mode

  def test_mode_string
    # should be done in test_set_mode
  end # def test_mode_string

  def test_set_mode
    t = PRUNE::IRCState.new("nick", "user", "name", "host")
    assert_no_exception {t.set_mode("+ai")}
    assert_equal(true, t.has_mode?(PRUNE::ModeList::MODE_AWAY))
    assert_equal(true, t.has_mode?(PRUNE::ModeList::MODE_INVISIBLE))
    assert_equal("+ai", t.mode_string)
    assert_equal(["AWAY", "INVISIBLE"], t.mode)
    assert_equal(["AWAY"], t.mode(PRUNE::ModeList::MODE_AWAY))
    assert_equal([], t.mode(PRUNE::ModeList::MODE_WALLOPS))
    assert_no_exception {t.set_mode("-i")}
    assert_no_exception {t.has_mode?(PRUNE::ModeList::MODE_INVISIBLE)}
    assert_no_exception {t.set_mode("-!")}
    assert_equal("[BUG] unknown nick mode: \"!\"", TestPRUNE__IRCState.get_msg)
    TestPRUNE__IRCState.set_msg(nil)
    assert_no_exception {t.clear_mode}
    assert_equal("+", t.mode_string)
    assert_equal([], t.mode(PRUNE::ModeList::MODE_AWAY))
  end # def test_set_mode

  def test_clear_mode
    # should be done in test_set_mode
  end # def test_clear_mode

end # class TestPRUNE__IRCState

class TestPRUNE__ChannelStateReadOnly < RUNIT::TestCase

  class << self
    def set_msg(msg)
      @@msg = msg
    end # def set_msg
    def get_msg
      @@msg
    end # def get_msg
  end

  def setup
    @@msg = nil
    def PRUNE._output(msg)
      TestPRUNE__ChannelStateReadOnly.set_msg(msg)
    end # def 
  end # def setup

  def teardown
    def PRUNE._output(msg)
      Kernel.printf("%s\n", msg)
    end # def 
  end # def teardown

  def test_functional
    assert_no_exception {t = PRUNE::ChannelStateReadOnly.new(PRUNE::ChannelState.new("#foo"))}
    assert_exception(ArgumentError) {t = PRUNE::ChannelStateReadOnly.new(0)}
    o = PRUNE::ChannelState.new("#foo")
    t = PRUNE::ChannelStateReadOnly.new(o)
    assert_equal(nil, t.topic)
    assert_exception(NoMethodError) {t.topic = "foo"}
    assert_no_exception {o.topic = "foo"}
    assert_equal("foo", t.topic)
    assert_exception(NoMethodError) {t.join("foo")}
    assert_no_exception {o.join("foo")}
    assert_exception(NoMethodError) {t.leave("foo")}
    assert_exception(NoMethodError) {t.set_oper("foo", true)}
    assert_equal(false, t.has_oper?("foo"))
    assert_no_exception {o.set_oper("foo", true)}
    assert_equal(true, t.has_oper?("foo"))
    assert_exception(NoMethodError) {t.clear_oper}
    assert_exception(NoMethodError) {t.set_voice("foo", true)}
    assert_equal(false, t.has_voice?("foo"))
    assert_no_exception {o.set_voice("foo", true)}
    assert_equal(true, t.has_voice?("foo"))
    assert_exception(NoMethodError) {t.clear_voice}
    assert_exception(NoMethodError) {t.change_nick("foo","bar")}
    assert_exception(NoMethodError) {t.set_mode("+t")}
    assert_exception(NoMethodError) {t.clear_mode}
    assert_no_exception {o.set_mode("+tn")}
    assert_equal("+ovtn foo foo", t.mode_string)
  end # def test_functional

end # class TestPRUNE__ChannelStateReadOnly

class TestPRUNE__IRCStateReadOnly < RUNIT::TestCase

  class << self
    def set_msg(msg)
      @@msg = msg
    end # def set_msg
    def get_msg
      @@msg
    end # def get_msg
  end

  def setup
    @@msg = nil
    def PRUNE._output(msg)
      TestPRUNE__IRCStateReadOnly.set_msg(msg)
    end # def 
  end # def setup

  def teardown
    def PRUNE._output(msg)
      Kernel.printf("%s\n", msg)
    end # def 
  end # def teardown

  def test_functional
    assert_no_exception {t = PRUNE::IRCStateReadOnly.new(PRUNE::IRCState.new("nick", "user", "name", "host"))}
    assert_exception(ArgumentError) {t = PRUNE::IRCStateReadOnly.new(0)}
    o = PRUNE::IRCState.new("nick", "user", "name", "host")
    t = PRUNE::IRCStateReadOnly.new(o)
    assert_equal("nick", t.nick)
    assert_exception(NoMethodError) {t.nick = "bar"}
    assert_no_exception {o.nick = "bar"}
    assert_equal("bar", t.nick)
    assert_exception(NoMethodError) {t.connected = true}
    assert_exception(NoMethodError) {t.listened = true}
    assert_exception(NoMethodError) {t.authenticated = true}
    assert_exception(NoMethodError) {t.loggedin = true}
    assert_exception(NoMethodError) {t.quit("foo")}
    assert_exception(NoMethodError) {t.set_mode("+a")}
    assert_exception(NoMethodError) {t.clear_mode}
    assert_equal("+", t.mode_string)
    assert_no_exception {o.set_mode("+a")}
    assert_equal("+a", t.mode_string)
  end # def test_functional

end # class TestPRUNE__IRCStateReadOnly


if $0 == __FILE__ then
  begin
    require 'main'
  rescue LoadError
    require 'tests/main'
  end
end
